#include <cassert>
#include <cstdlib>
#include "ByReferencePass.h"
#include "CodeGen.h"
#include "CodeGen_Bash.h"
#include "Compile.h"
#include "Config.h"
#include "Parser.h"
#include "ReturnValuesPass.h"
#include "TypeChecker.h"
#include "Util.h"

using namespace Bish;

namespace {

// Add necessary stdlib functions to the given module.
void link_stdlib(Bish::Module *m) {
    Parser p;
    Module *stdlib = p.parse(get_stdlib_path());
    // TODO: this seems clunky. Trying to avoid importing stdlib if
    // the user is compiling stdlib itself.
    if (m->path.compare(stdlib->path) != 0) {
        m->import(stdlib);
    }
}

// Run an ordered list of post-link passes over the IR.
void link_time_passes(Bish::Module *m) {
    // Type checking
    TypeChecker types;
    m->accept(&types);

    // Adjust the IR to handle values that should be passed by
    // reference (e.g. arrays) to functions.
    ByReferencePass refs;
    m->accept(&refs);

    // Convert function return values into global variable
    // assignments.
    ReturnValuesPass retvals;
    m->accept(&retvals);
}

}

// Link and compile the given Module using the given code generator.
void Bish::compile(Module *m, CodeGenerator *cg) {
    link_stdlib(m);

    link_time_passes(m);
    
    cg->ostream() << "#!/usr/bin/env bash\n"
    << "# Autogenerated script, compiled from the Bish language.\n"
    << "# Bish version " << BISH_VERSION << "\n"
    << "# Please see " << BISH_URL << " for more information about Bish.\n";
    m->accept(cg);

    cg->ostream().flush();
}
